{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How to Add Breakpoints\n",
    "\n",
    "When creating LangGraph agents, it is often nice to add a human-in-the-loop component.\n",
    "This can be helpful when giving them access to tools.\n",
    "Often in these situations you may want to manually approve an action before taking.\n",
    "\n",
    "This can be in several ways, but the primary supported way is to add an \"interrupt\" before a node is executed.\n",
    "This interrupts execution at that node.\n",
    "You can then resume from that spot to continue.  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup\n",
    "\n",
    "### Code for your graph\n",
    "\n",
    "In this how-to we use a simple ReAct style hosted graph (you can see the full code for defining it [here](https://langchain-ai.github.io/langgraph/how-tos/human_in_the_loop/breakpoints/)). The important thing is that there are two nodes (one named `agent` that calls the LLM, and one named `action` that calls the tool), and a routing function from `agent` that determines whether to call `action` next or just end the graph run (the `action` node always calls the `agent` node after execution).\n",
    "\n",
    "### SDK Initialization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langgraph_sdk import get_client\n",
    "client = get_client()\n",
    "assistants = await client.assistants.search()\n",
    "assistants = [a for a in assistants if not a['config']]\n",
    "assistant = assistants[0]\n",
    "assistant_id = assistant['assistant_id']\n",
    "thread = await client.threads.create()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Adding a breakpoint\n",
    "\n",
    "We now want to add a breakpoint in our graph run, which we will do before a tool is called.\n",
    "We can do this by adding `interrupt_before=[\"action\"]`, which tells us to interrupt before calling the action node.\n",
    "We can do this either when compiling the graph or when kicking off a run.\n",
    "Here we will do it when kicking of a run, if you would like to to do it at compile time you need to edit the python file where your graph is defined and add the `interrupt_before` parameter when you call `.compile`.\n",
    "\n",
    "First let's access our hosted Langgraph instance through the SDK:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And, now let's compile it with a breakpoint before the tool node:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Receiving new event of type: metadata...\n",
      "{'run_id': '3b77ef83-687a-4840-8858-0371f91a92c3'}\n",
      "\n",
      "\n",
      "\n",
      "Receiving new event of type: data...\n",
      "{'agent': {'messages': [{'content': [{'id': 'toolu_01HwZqM1ptX6E15A5LAmyZTB', 'input': {'query': 'weather in san francisco'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}], 'additional_kwargs': {}, 'response_metadata': {}, 'type': 'ai', 'name': None, 'id': 'run-e5d17791-4d37-4ad2-815f-a0c4cba62585', 'example': False, 'tool_calls': [{'name': 'tavily_search_results_json', 'args': {'query': 'weather in san francisco'}, 'id': 'toolu_01HwZqM1ptX6E15A5LAmyZTB'}], 'invalid_tool_calls': []}]}}\n",
      "\n",
      "\n",
      "\n",
      "Receiving new event of type: end...\n",
      "None\n",
      "\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "input = {\"messages\": [{\"role\": \"human\", \"content\": \"what's the weather in sf\"}]}\n",
    "async for chunk in client.runs.stream(\n",
    "    thread[\"thread_id\"],\n",
    "    assistant_id,\n",
    "    input=input,\n",
    "    stream_mode=\"updates\",\n",
    "    interrupt_before=[\"action\"],\n",
    "):\n",
    "    print(f\"Receiving new event of type: {chunk.event}...\")\n",
    "    print(chunk.data)\n",
    "    print(\"\\n\\n\")"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
